package com.google.code.p.restrpc.core.async;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.util.Properties;

import org.apache.commons.lang.StringUtils;

/**
 * @author dz
 */
public class AsyncServiceManagers {
    
    private static AsyncServiceManager instance = newAsyncRpcManager();
    
    /**
     * @return
     */
    public static AsyncServiceManager getAsyncRpcManager() {
        return instance;
    }
    
    /**
     * @return
     */
    public static AsyncServiceManager newAsyncRpcManager() {
        InputStream inputStream = Thread.currentThread()
                                        .getContextClassLoader()
                                        .getResourceAsStream("asyncrpc.manager.properties");
        if (inputStream != null) {
            try {
                Properties properties = new Properties();
                properties.load(inputStream);
                return newAsyncRpcManager(properties);
            }
            catch (IOException e) {
                throw new AsyncRpcConfigurationException("Load asyncrpc.manager.properties failed!");
            }
        }
        
        inputStream = Thread.currentThread()
                            .getContextClassLoader()
                            .getResourceAsStream("META-INF/configuration/asyncrpc.manager.properties");
        
        if (inputStream != null) {
            try {
                Properties properties = new Properties();
                properties.load(inputStream);
                return newAsyncRpcManager(properties);
            }
            catch (IOException e) {
                throw new AsyncRpcConfigurationException("Load META-INF/configuration/asyncrpc.manager.properties failed!");
            }
        }
        
        throw new AsyncRpcConfigurationException("asyncrpc.manager.properties not found!");
    }
    
    /**
     * @param properties
     * @return
     */
    public static AsyncServiceManager newAsyncRpcManager(Properties properties) {
        String implClassName = properties.getProperty(AsyncServiceManagerFactory.class.getName());
        
        if (StringUtils.isEmpty(implClassName)) {
            throw new AsyncRpcConfigurationException("The implementor for " + AsyncServiceManagerFactory.class.getName()
                                                     + " not specifed!");
        }
        
        try {
            Class implClazz = Class.forName(implClassName);
            Constructor constructor = implClazz.getConstructor(new Class[] { Properties.class });
            if (constructor == null) {
                throw new AsyncRpcConfigurationException("Constructor " + implClassName
                                                         + "(Properties.class) not found!");
            }
            return ((AsyncServiceManagerFactory) constructor.newInstance(properties)).getInstance();
        }
        catch (AsyncRpcConfigurationException e) {
            throw e;
        }
        catch (ClassNotFoundException e) {
            throw new AsyncRpcConfigurationException("Clkass " + implClassName
                                                     + " not found!", e);
        }
        catch (Exception e) {
            throw new AsyncRpcConfigurationException("Instantiate " + implClassName
                                                             + " faild!",
                                                     e);
        }
    }
}
